package com.mf.basic.services;

import cn.dev33.satoken.stp.StpUtil;
import com.mf.basic.entity.DtoUser;
import com.mf.basic.enums.EnumBaseParams;
import com.mf.basic.exceptions.MyException;
import com.mf.basic.mapper.MapperUser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Map;

/**
 * Created by Luke on 2025/3/7 17:06.
 */
@Service
@Transactional
public class ServiceUser extends ServiceImpl<MapperUser, DtoUser> implements BaseService<DtoUser>{

    @Resource
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public LambdaQueryWrapper<DtoUser> fillParams(Map<String, Object> params) {
        LambdaQueryWrapper<DtoUser> qw = loadQw();
        Object tmp = params.get("key");
        if (paramNotNull(tmp)) {
            String k = tmp + "";
            qw.and(i->i.like(DtoUser::getUsername, k).or()
                    .like(DtoUser::getNick, k).or()
                    .like(DtoUser::getRemark, k));
        }
        tmp = params.get("roleId");
        qw.exists(paramNotNull(tmp), "SELECT 1 FROM sys_user_role WHERE sys_user_role.user_id = sys_user.id AND sys_user_role.role_id={0}", tmp);
        tmp = params.get("neRoleId");
        qw.notExists(paramNotNull(tmp), "SELECT 1 FROM sys_user_role WHERE sys_user_role.user_id = sys_user.id AND sys_user_role.role_id={0}", tmp);
        tmp = params.get("status");
        qw.eq(paramNotNull(tmp), DtoUser::getStatus, tmp);
        qw.orderByAsc(DtoUser::getStatus);
        return qw;
    }

    /**
     * 根据用户名查询用户
     * @param username 用户名
     * @return DtoUser
     */
    public DtoUser findByUserName(String username) {
        LambdaQueryWrapper<DtoUser> queryWrapper = loadQw();
        queryWrapper.eq(DtoUser::getUsername, username);
        return this.getOne(queryWrapper);
    }

    /**
     * 新增用户
     * @param obj 用户对象
     */
    public void doAdd(DtoUser obj){
        String douser = (String) StpUtil.getSession().get(EnumBaseParams.douser.name());
        DtoUser user = new DtoUser();
        user.setUsername(obj.getUsername())
                .setNick(obj.getNick())
                .setPassword(passwordEncoder.encode(obj.getPassword()))
                .setRemark(obj.getRemark())
                .setDouser(douser);
        try {
            this.save(user);
        } catch (Exception e) {
            throw new MyException("用户名已经存在, 请检查");
        }
    }

    /**
     * 管理员修改密码
     * @param id ID
     * @param newPassword 新密码
     */
    public void upPasswordManager(long id, String newPassword) {
        long loginId = (long) StpUtil.getSession().get(EnumBaseParams.userId.name());
        if(id == 1){
            Assert.state(loginId == 1, "您不能修改超级管理员密码, 请检查");
        }
        findCheckById(Math.toIntExact(id), true);
        DtoUser user = new DtoUser()
                .setId(id)
                .setPassword(passwordEncoder.encode(newPassword));
        this.updateById(user);
    }

    /**
     * 用户修改密码
     * @param newPassword 新密码
     */
    public void upPasswordUser(String oldPassword, String newPassword) {
        long id = (long) StpUtil.getSession().get(EnumBaseParams.userId.name());
        DtoUser user = findCheckById(Math.toIntExact(id), true);
        Assert.state(passwordEncoder.matches(oldPassword, user.getPassword()), "旧密码错误, 请检查");
        user.setPassword(passwordEncoder.encode(newPassword));
        this.updateById(user);
    }

    /**
     * 修改状态
     * @param id ID
     * @param status 状态
     */
    public void upStatus(long id, int status) {
        DtoUser user = findCheckById(Math.toIntExact(id), true);
        Assert.state(user.getId() != 1, "管理员账号不允许操作, 请检查");
        if (status == 1 && user.getStatus() == 1) {
            throw new MyException("用户已经禁用, 请勿重复操作");
        }
        if (status == 0 && user.getStatus() == 0) {
            throw new MyException("用户已经启用, 请勿重复操作");
        }
        user.setStatus(status);
        this.updateById(user);
    }

    /**
     * 修改用户信息
     * @param user 用户信息
     */
    public void doUpdate(DtoUser user) {
        findCheckById(Math.toIntExact(user.getId()), true);
        Assert.state(user.getId() != 1, "管理员账号不允许操作, 请检查");
        DtoUser obj = new DtoUser()
                .setId(user.getId())
                .setNick(user.getNick())
                .setRemark(user.getRemark());
        this.updateById(obj);
    }

}
